from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.db.models import Q
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse
from django.contrib.auth.models import User
from article.forms import ArticlePostForm
from article.models import ArticlePost, ArticleColumn
from comment.forms import CommentForm
from comment.models import Comment
import markdown


# 所有文章，引入分页
def article_list(request):
    # articles_list = ArticlePost.objects.all()
    # 根据GET请求中查询条件，从 url 中提取查询参数
    search = request.GET.get('search')
    order = request.GET.get('order')
    column = request.GET.get('column')
    tag = request.GET.get('tag')
    # 初始化查询集
    article_list = ArticlePost.objects.all()
    # 搜索查询集
    if search:
        # 用 Q对象 进行联合搜索
        article_list = article_list.filter(
            Q(title__icontains=search) |
            Q(body__icontains=search)
        )
    else:
        # 将 search 参数重置为空
        search = ''
    # 栏目、标签查询集
    if column is not None and column.isdigit():
        article_list = article_list.filter(column=column)
    if tag and tag != 'None':
        article_list = article_list.filter(tags__name__in=[tag])
    # 查询集排序
    if order == 'total_views':
        article_list = article_list.order_by('-total_views')

    # 每页显示n篇文章
    paginator = Paginator(article_list, 3)
    # 获取 url 中的页码
    page = request.GET.get('page')
    # 将导航对象对应的页码内容返回给 articles_page
    articles = paginator.get_page(page)
    # 传递给模板（templates）的对象
    context = {'articles': articles, 'order': order, 'search': search, 'column': column, 'tag': tag}
    return render(request, 'article/list.html', context)


# 文章详情
def article_detail(request, id):
    # article = ArticlePost.objects.get(id=id)
    article = get_object_or_404(ArticlePost, id=id)
    comments = Comment.objects.filter(article=id)
    # 浏览量
    article.total_views += 1
    # update_fields=[]指定了数据库只更新total_views字段，优化执行效率。
    article.save(update_fields=['total_views'])
    # markdown 渲染
    md = markdown.Markdown(
        extensions=[
            'markdown.extensions.extra',
            'markdown.extensions.codehilite',  # 高亮
            'markdown.extensions.toc',  # 文章目录
        ]
    )
    article.body = md.convert(article.body)
    comment_form = CommentForm()  # 引入评论表单
    context = {'article': article, 'toc': md.toc, 'comments': comments, 'comment_form': comment_form}
    return render(request, 'article/detail.html', context)


# 写文章的视图
@login_required(login_url='/userprofile/login/')
def article_create(request):
    # 判断用户是否提交数据
    if request.method == "POST":
        # 将提交的数据赋值到表单实例中
        article_post_form = ArticlePostForm(data=request.POST, files=request.FILES)
        # 判断提交的数据是否满足模型的要求
        if article_post_form.is_valid():
            # 保存数据，但暂时不提交到数据库中，因为author还未指定
            new_article = article_post_form.save(commit=False)
            # 指定 目前登录的用户 为作者
            # 此时请重新创建用户，并传入此用户的id
            new_article.author = User.objects.get(id=request.user.id)
            if request.POST['column'] != 'none':
                new_article.column = ArticleColumn.objects.get(id=request.POST['column'])
            # 将新文章保存到数据库中
            new_article.save()
            article_post_form.save_m2m()
            return redirect("article:article_list")
        else:
            return HttpResponse("表单内容有误，请重新填写")
    # 用户请求数据
    else:
        article_post_form = ArticlePostForm()
        columns = ArticleColumn.objects.all()
        context = {'article_post_form': article_post_form, 'columns': columns}
        return render(request, 'article/create.html', context)


# 删除文章
@login_required(login_url='/userprofile/login/')
def article_delete(request, id):
    # 根据 id 获取需要删除的文章
    article = ArticlePost.objects.get(id=id)
    if request.user != article.author:
        return HttpResponse("抱歉，你无权删除该篇文章")
    article.delete()
    return redirect("article:article_list")


# 安全删除文章
@login_required(login_url='/userprofile/login/')
def article_safe_delete(request, id):
    article = ArticlePost.objects.get(id=id)
    if request.user != article.author:
        return HttpResponse("抱歉，你无权删除该篇文章")
    if request.method == 'POST':
        article = ArticlePost.objects.get(id=id)
        article.delete()
        return redirect("article:article_list")
    else:
        return HttpResponse("仅允许post请求")


# 修改文章
@login_required(login_url='/userprofile/login/')
def article_update(request, id):
    '''
    通过 POST 方法提交表单，更新 title、body 字段
    GET 方法进入初始化表单页面
    id 为需要更新的文章 id
    '''
    article = ArticlePost.objects.get(id=id)
    # 后端鉴权（仅仅在前端模板中鉴权是不够的）
    if request.user != article.author:
        return HttpResponse("抱歉，你无权修改该篇文章")
    if request.method == "POST":
        article_post_form = ArticlePostForm(data=request.POST)
        if article_post_form.is_valid():
            article.title = request.POST['title']
            article.body = request.POST['body']
            if request.POST['column'] != 'none':
                article.column = ArticleColumn.objects.get(id=request.POST['column'])
            else:
                article.column = None
            article.tags.set(*request.POST.get('tags').split(','), clear=True)
            if request.FILES.get('avatar'):
                article.avatar = request.FILES.get('avatar')
            article.save()
            return redirect("article:article_detail", id=id)
        else:
            return HttpResponse("context of format error, please try again.")
    else:
        article_post_form = ArticlePostForm()
        columns = ArticleColumn.objects.all()
        context = {'article': article,
                   'article_post_form': article_post_form,
                   'columns': columns,
                   'tags': ','.join([x for x in article.tags.names()])
                   }
        return render(request, 'article/update.html', context)
